package com.xinqi.common.base.response;

import com.xinqi.common.base.constants.C.HttpStatus;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.error.ErrorDetail;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Objects;

/**
 * 响应信息主体
 *
 * @author dgyu
 */
@Data
@NoArgsConstructor
@Schema(description = "响应信息主体")
public class R<T> implements Serializable {
    /**
     * 成功
     */
    public static final int SUCCESS = HttpStatus.OK;
    /**
     * 失败
     */
    public static final int FAIL = HttpStatus.INTERNAL_SERVER_ERROR;
    public static final String SUCCESS_MSG = "操作成功";
    public static final String ERROR_MSG = "操作失败";

    public static final String SYSTEM_MSG = "服务器繁忙，请稍后重试!";


    /**
     * 消息状态码
     */
    @Schema(description = "消息状态码", example = "200")
    private int code;

    /**
     * 消息内容
     */
    @Schema(description = "消息内容", example = "操作成功")
    private String msg;

    /**
     * 请求路径
     */
    @Schema(description = "请求路劲", example = "/app/user/login")
    private String path;

    /**
     * 数据对象
     */
    @Schema(description = "数据对象")
    private T data;

    public static <T> R<T> ok() {
        return ok("操作成功");
    }

    public static <T> R<T> ok(T data) {
        return ok(SUCCESS_MSG, data);
    }

    public static <T> R<T> ok(String msg) {
        return ok(SUCCESS, msg, null);
    }

    public static <T> R<T> ok(String msg, T data) {
        return ok(SUCCESS, msg, data);
    }

    public static <T> R<T> ok(int code, String msg, T data) {
        return of(data, code, Objects.isNull(msg) ? SUCCESS_MSG : msg, null);
    }

    public static <T> R<T> data(T data) {
        return data(data, SUCCESS_MSG);
    }

    public static <T> R<T> data(String msg) {
        return data(null, msg);
    }

    public static <T> R<T> data(T data, String msg) {
        return of(data, SUCCESS, msg, null);
    }

    public static <T> R<T> fail() {
        return fail(FAIL, ERROR_MSG);
    }

    public static <T> R<T> fail(String msg) {
        return fail(FAIL, msg == null ? SYSTEM_MSG : msg);
    }

    public static <T> R<T> fail(T data) {
        return fail(FAIL, ERROR_MSG, data);
    }

    public static <T> R<T> fail(String msg, T data) {
        return fail(FAIL, msg == null ? SYSTEM_MSG : msg, data);
    }

    public static <T> R<T> fail(int code, String msg) {
        return fail(code, msg == null ? SYSTEM_MSG : msg, null);
    }

    public static <T> R<T> fail(int code, String msg, T data) {
        return fail(code, msg, data, null);
    }

    public static <T> R<T> fail(int code, String msg, T data, String path) {
        return of(data, code, msg, path);
    }

    public static <T> R<T> error() {
        return error(ERROR_MSG);
    }

    public static <T> R<T> error(String msg) {
        return error(CommonErrors.BAD_REQUEST.getCode(), msg, null);
    }

    public static <T> R<T> error(Integer code, String msg) {
        return error(code, msg, null);
    }

    public static <T> R<T> error(Integer code, String msg, String path) {
        return error(code, msg, path, null);
    }

    public static <T> R<T> error(Integer code, String msg, String path, T data) {
        return of(data, code, msg, path);
    }

    /**
     * 返回警告消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static <T> R<T> warn(String msg) {
        return warn(msg, null);
    }

    /**
     * 返回警告消息
     *
     * @param msg  返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static <T> R<T> warn(String msg, T data) {
        return of(data, HttpStatus.BAD_REQUEST, msg, null);
    }

    private static <T> R<T> of(T data, int code, String msg, String path) {
        R<T> r = new R<>();
        r.setCode(code);
        r.setData(data);
        r.setMsg(msg);
        r.setPath(path);
        return r;
    }

    public static <T> Boolean isError(R<T> ret) {
        return !isSuccess(ret);
    }

    public static <T> Boolean isSuccess(R<T> ret) {
        return ret.isOk();
    }

    public Boolean isOk() {
        return Objects.equals(R.SUCCESS, code);
    }

    /**
     * 获取返回结果中的数据对象
     *
     * @param r   返回结果
     * @param <T> 数据对象
     * @return 返回数据对象
     */
    public static <T> T as(R<T> r) {
        if (r.isOk()) {
            return r.getData();
        }
        throw ErrorDetail.with(r.getCode(), r.getMsg()).asException();
    }

    /**
     * 获取返回结果中的数据对象
     *
     * @param r   返回结果
     * @param msg 如果请求失败，则返回对应的错误消息
     * @param <T> 数据对象
     * @return 返回数据对象
     */
    public static <T> T as(R<T> r, String msg) {
        if (r.isOk()) {
            return r.getData();
        }
        throw ErrorDetail.with(r.getCode(), msg).asException();
    }

    /**
     * 获取返回结果中的数据对象
     *
     * @param r    返回结果
     * @param code 如果请求失败，则返回对应的错误编号
     * @param msg  如果请求失败，则返回对应的错误消息
     * @param <T>  数据对象
     * @return 返回数据对象
     */
    public static <T> T as(R<T> r, int code, String msg) {
        if (r.isOk()) {
            return r.getData();
        }
        throw ErrorDetail.with(code, msg).asException();
    }

}
